// Copyright 叶湘 ( weixin:yexiang841, email:yexiang841@qq.com ), Shitouren Studio. All Rights Reserved.

#include "PawnState/Q3D_CPPC_PawnState.h"
#include "PawnState/Q3D_CPPU_PawnState.h"
#include "PawnState/Q3D_CPPI_PawnState.h"
#include "GameState/Q3D_CPPA_GameState.h"
#include "Pawn/Q3D_CPPA_SpectatorPawn.h"
#include "PlayerController/Q3D_CPPI_PlayerController.h"
#include "Misc/Guid.h"
#include "Logger/Q3D_CPPU_Logger.h"

// Sets default values for this component's properties
UQ3D_CPPC_PawnState::UQ3D_CPPC_PawnState()
{
	// Set this component to be initialized when the game starts, and to be ticked every frame.  You can turn these features
	// off to improve performance if you don't need them.
	PrimaryComponentTick.bCanEverTick = true;

	// ...
}

// Called when the game starts
void UQ3D_CPPC_PawnState::BeginPlay()
{
	Super::BeginPlay();

	// ...
	// 往GameState中注册自己
	bool bool_success;
	FString string_log;
	this->Q3D_F_Pawn_Regist(bool_success, string_log);
}

// Called every frame
void UQ3D_CPPC_PawnState::TickComponent(float DeltaTime, ELevelTick TickType, FActorComponentTickFunction *ThisTickFunction)
{
	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);

	// ...
}
void UQ3D_CPPC_PawnState::Q3D_F_Pawn_Regist(bool &bool_success, FString &string_log)
{
	// if( ! this->GetOwner() ){
	// 	bool_success = false;
	// 	string_log = "Owner_Not_Ready";
	// 	Q3D_LOG( Warning, string_log );
	// 	return;
	// }
	// Owner 类型检查，只针对 Pawn 类型的 Owner 操作
	APawn *ptr_a_pawn_owner = Cast<APawn>(this->GetOwner());
	if (!ptr_a_pawn_owner)
	{
		string_log = "Cast_To_Q3D_CPPA_Pawn_Failed";
		bool_success = false;
		Q3D_LOG(Warning, string_log);
		return;
	}
	// Controller类型区分
	AAIController *ptr_ai_controller = Cast<AAIController>(ptr_a_pawn_owner->GetController());
	APlayerController *ptr_player_controller = Cast<APlayerController>(ptr_a_pawn_owner->GetController());
	if (ptr_ai_controller)
	{
		this->Ptr_A_AIController_Possessed = ptr_ai_controller;
		if (this->Bool_Config_AutoAIControllerPossessed)
		{
			this->Ptr_A_AIController_AutoSaved = ptr_ai_controller;
		}
	}
	else if (ptr_player_controller)
	{
		this->Ptr_A_PlayerController_Possessed = ptr_player_controller;
	}
	else
	{
		string_log = "Unknown_Controller_Type";
		bool_success = false;
		Q3D_LOG(Warning, string_log);
		return;
	}
	// Q3D_CPPI_PawState接口判断
	IQ3D_CPPI_PawnState *ptr_i_pawn_state_owner = Cast<IQ3D_CPPI_PawnState>(ptr_a_pawn_owner);
	if (!ptr_i_pawn_state_owner)
	{
		string_log = "Cast_To_Q3D_CPPI_PawnState_Failed";
		bool_success = false;
		Q3D_LOG(Warning, string_log);
		return;
	}
	// 创建PawnState
	UQ3D_CPPU_PawnState *ptr_u_pawn_state_new = NewObject<UQ3D_CPPU_PawnState>(ptr_a_pawn_owner);
	ptr_u_pawn_state_new->Name_Id = FName(FGuid::NewGuid().ToString());
	ptr_u_pawn_state_new->String_NickName = ptr_a_pawn_owner->GetName();
	ptr_u_pawn_state_new->Ptr_A_Pawn = ptr_a_pawn_owner;
	this->Ptr_U_PawnState = ptr_u_pawn_state_new;
	// Q3D_CPPA_GameState类型判断
	AQ3D_CPPA_GameState *ptr_a_game_state = Cast<AQ3D_CPPA_GameState>(GetWorld()->GetGameState());
	if (!ptr_a_game_state)
	{
		string_log = "Cast_To_Q3D_CPPA_GameState_Failed";
		bool_success = false;
		Q3D_LOG(Warning, string_log);
		return;
	}
	// 在GameState中注册
	if (ptr_a_pawn_owner->GetClass()->IsChildOf(ASpectatorPawn::StaticClass()))
	{
		ptr_a_game_state->Q3D_F_PawnState_Spectator_Set(ptr_u_pawn_state_new, bool_success, string_log);
	}
	else
	{
		ptr_a_game_state->Q3D_F_PawnState_Inc(ptr_u_pawn_state_new, bool_success, string_log);
	}
	if (!bool_success)
	{
		Q3D_LOG(Warning, string_log);
		return;
	}
	// 成功的话 bool_success 和 string_log 也已经设置好了
	return;
}

void UQ3D_CPPC_PawnState::Q3D_F_Pawn_Unregist(bool &bool_success, FString &string_log)
{
	// if( ! this->GetOwner() ){
	// 	bool_success = false;
	// 	string_log = "Owner_Not_Ready";
	// 	Q3D_LOG( Warning, string_log );
	// }
	// Owner 类型检查，只针对 Pawn 类型的 Owner 操作
	APawn *ptr_a_pawn_owner = Cast<APawn>(this->GetOwner());
	if (!ptr_a_pawn_owner)
	{
		string_log = "Cast_To_Q3D_CPPA_Pawn_Failed";
		bool_success = false;
		Q3D_LOG(Warning, string_log);
		return;
	}
	// Q3D_CPPI_PawState 接口判断
	IQ3D_CPPI_PawnState *ptr_i_pawn_state_owner = Cast<IQ3D_CPPI_PawnState>(ptr_a_pawn_owner);
	if (!ptr_i_pawn_state_owner)
	{
		string_log = "Cast_To_Q3D_CPPI_PawnState_Failed";
		bool_success = false;
		Q3D_LOG(Warning, string_log);
		return;
	}
	// 获取 PlayerIndex 后面要用
	int32 int_player_index;
	ptr_i_pawn_state_owner->Execute_Q3D_IF_PlayerIndex_Get(ptr_a_pawn_owner, int_player_index);
	// 引用检查，没保存说明尚未注册成功
	if (!this->Ptr_U_PawnState)
	{
		string_log = "PawnState_Not_Ready";
		bool_success = false;
		Q3D_LOG(Warning, string_log);
		return;
	}
	// Q3D_CPPA_GameState 类型判断
	AQ3D_CPPA_GameState *ptr_a_game_state = Cast<AQ3D_CPPA_GameState>(GetWorld()->GetGameState());
	if (!ptr_a_game_state)
	{
		string_log = "Cast_To_Q3D_CPPA_GameState_Failed";
		bool_success = false;
		Q3D_LOG(Warning, string_log);
		return;
	}
	// 在 GameState 中注销
	UQ3D_CPPU_PawnState *ptr_u_pawn_state_next = nullptr;
	if (ptr_a_pawn_owner->GetClass()->IsChildOf(ASpectatorPawn::StaticClass()))
	{
		ptr_a_game_state->Q3D_F_PawnState_Spectator_Unset(int_player_index, bool_success, string_log);
	}
	else
	{
		ptr_a_game_state->Q3D_F_PawnState_Dec(this->Ptr_U_PawnState, bool_success, string_log, ptr_u_pawn_state_next);
	}
	if (!bool_success)
	{
		Q3D_LOG(Warning, string_log);
		return;
	}
	// Controller 类型区分
	AAIController *ptr_ai_controller = Cast<AAIController>(ptr_a_pawn_owner->GetController());
	APlayerController *ptr_player_controller = Cast<APlayerController>(ptr_a_pawn_owner->GetController());
	if (ptr_ai_controller)
	{
		// 解除 AIController 控制并愣在原地
		ptr_ai_controller->UnPossess();
	}
	else if (ptr_player_controller)
	{
		if (ptr_u_pawn_state_next)
		{
			// 有下一个可用的 Pawn 则切换 PlayerController 操控
			ptr_player_controller->Possess(ptr_u_pawn_state_next->Ptr_A_Pawn);
		}
		else
		{
			// 没有下一个可用的 Pawn
			// 看有没有配置漫游
			if (this->Bool_Config_AutoSpectatorControlled)
			{
				// 配置了漫游
				// 获取漫游 SpectatorPawn/PawnState
				UQ3D_CPPU_PawnState *ptr_u_pawn_state_spectator;
				ptr_a_game_state->Q3D_F_PawnState_Spectator_Get(int_player_index, ptr_u_pawn_state_spectator);
				if (ptr_u_pawn_state_spectator)
				{
					// 已注册过漫游 SpectatorPawn/PawnState
					ptr_player_controller->Possess(ptr_u_pawn_state_spectator->Ptr_A_Pawn);
				}
				else
				{
					// 还没有注册过漫游 SpectatorPawn/PawnState
					// 注册一个，Q3D_CPPA_SpectatorPawn 扩展了自动注册能力
					AQ3D_CPPA_SpectatorPawn *ptr_a_spectator_pawn = GetWorld()->SpawnActorDeferred<AQ3D_CPPA_SpectatorPawn>(AQ3D_CPPA_SpectatorPawn::StaticClass(), ptr_a_pawn_owner->GetTransform());
					if (ptr_a_spectator_pawn)
					{
						ptr_a_spectator_pawn->Int_PlayerIndex = int_player_index;
						ptr_a_spectator_pawn->FinishSpawning(ptr_a_pawn_owner->GetTransform());
						// 开始漫游
						ptr_player_controller->Possess(ptr_a_spectator_pawn);
					}
					else
					{
						Q3D_LOG(Warning, "Spawn_Ptr_A_SpectatorPawn_Failed");
					}
				}
			}
			else
			{
				// 没有配置漫游
				// 解除 PlayerController 控制并愣在原地（这样好吗？）
				ptr_player_controller->UnPossess();
			}
		}
		this->Ptr_A_PlayerController_Possessed = ptr_player_controller;
	}
	else
	{
		string_log = "Unknown_Controller_Type " + ptr_a_pawn_owner->GetController()->GetClass()->GetName();
		bool_success = false;
		Q3D_LOG(Warning, string_log);
		return;
	}
	// 成功的话 bool_success 和 string_log 也已经设置好了
	// 指针置空
	this->Ptr_U_PawnState = nullptr;
	// 广播
	this->Ptr_U_PawnState->Q3D_ED_Pawn_Unregisted.Broadcast();
	return;
}

void UQ3D_CPPC_PawnState::Q3D_F_Pawn_Possessed(AController *ptr_controller_new)
{
	// if( ! this->GetOwner() ){
	// 	Q3D_LOG( Warning, "Owner_Not_Ready" );
	// 	return;
	// }
	// Owner 类型检查，只针对 Pawn 类型的 Owner 操作
	APawn *ptr_a_pawn_owner = Cast<APawn>(this->GetOwner());
	if (!ptr_a_pawn_owner)
	{
		Q3D_LOG(Warning, "Cast_To_APawn_Failed");
		return;
	}
	// Controller类型区分
	AAIController *ptr_ai_controller = Cast<AAIController>(ptr_controller_new);
	APlayerController *ptr_player_controller = Cast<APlayerController>(ptr_controller_new);
	if (ptr_ai_controller)
	{
		this->Ptr_A_AIController_Possessed = ptr_ai_controller;
		// 如果将来需要AI接管
		if (this->Bool_Config_AutoAIControllerPossessed)
		{
			this->Ptr_A_AIController_AutoSaved = ptr_ai_controller;
		}
	}
	else if (ptr_player_controller)
	{
		this->Ptr_A_PlayerController_Possessed = ptr_player_controller;
		// 如果是 Q3D_I_PlayerController 接口类型需要进行一次回调
		IQ3D_CPPI_PlayerController *ptr_i_player_controller = Cast<IQ3D_CPPI_PlayerController>(ptr_player_controller);
		if (ptr_i_player_controller)
		{
			bool bool_success = true;
			FString string_log = "";
			ptr_i_player_controller->Execute_Q3D_IF_Pawn_Possessed(ptr_player_controller, ptr_a_pawn_owner, bool_success, string_log);
		}
		// 引用检查，没保存说明尚未注册成功
		if (!this->Ptr_U_PawnState)
		{
			Q3D_LOG(Warning, "PawnState_Not_Ready");
		}
		else
		{
			// 广播
			this->Ptr_U_PawnState->Q3D_ED_Pawn_Possess_Reset.Broadcast(true);
		}
	}
	else
	{
		Q3D_LOG(Warning, "Unknown_Controller_Type " + ptr_a_pawn_owner->GetController()->GetClass()->GetName());
	}
	return;
}

void UQ3D_CPPC_PawnState::Q3D_F_Pawn_Unpossessed(AController *ptr_controller_old)
{
	// if( ! this->GetOwner() ){
	// 	Q3D_LOG( Warning, "Owner_Not_Ready" );
	// 	return;
	// }
	// Owner 类型检查，只针对 Pawn 类型的 Owner 操作
	APawn *ptr_a_pawn_owner = Cast<APawn>(this->GetOwner());
	if (!ptr_a_pawn_owner)
	{
		Q3D_LOG(Warning, "Cast_To_APawn_Failed");
		return;
	}
	// Controller 类型区分
	AAIController *ptr_ai_controller = Cast<AAIController>(ptr_controller_old);
	APlayerController *ptr_player_controller = Cast<APlayerController>(ptr_controller_old);
	if (ptr_ai_controller)
	{
		this->Ptr_A_AIController_Possessed = nullptr;
	}
	else if (ptr_player_controller)
	{
		this->Ptr_A_PlayerController_Possessed = nullptr;
		// 引用检查，没保存说明尚未注册成功
		if (!this->Ptr_U_PawnState)
		{
			Q3D_LOG(Warning, "PawnState_Not_Ready");
		}
		else
		{
			// 广播
			this->Ptr_U_PawnState->Q3D_ED_Pawn_Possess_Reset.Broadcast(false);
		}
		// 如果现在需要AI接管
		if (this->Bool_Config_AutoAIControllerPossessed)
		{
			if (this->Ptr_A_AIController_AutoSaved)
			{
				// AI 接管
				this->Ptr_A_AIController_AutoSaved->Possess(ptr_a_pawn_owner);
			}
			else
			{
				// 生成一个 AIController，并自动接管自己
				ptr_a_pawn_owner->SpawnDefaultController();
			}
		}
	}
	else
	{
		Q3D_LOG(Warning, "Unknown_Controller_Type " + ptr_a_pawn_owner->GetController()->GetClass()->GetName());
	}
	return;
}
